#include "DHT.h"
#include <Wire.h>
#include <ACROBOTIC_SSD1306.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Ticker.h>  // 添加Ticker库用于定时中断

#define LED 14
#define DHT11_DAT 2
#define LDR_DO 0
#define Buzzer_IO 12
#define Key_1 13
#define Key_2 15
#define Key_Yin 3

// WiFi连接配置
#define macUser_ESP8266_ApSsid          "iQOO 11"       // 要连接的热点的名称
#define macUser_ESP8266_ApPwd           "12345678"      // 要连接的热点的密钥

// OneNET MQTT配置
#define MQTT_CLIENT_ID    "demo"                     // 设备名称
#define MQTT_USER_NAME    "aCwL6bRLK9"                 // 产品ID
#define MQTT_PASSWD       "version=2018-10-31&res=products%2FaCwL6bRLK9%2Fdevices%2Fdemo&et=160000000000&method=md5&sign=olsMYj5CRqs%2BPvKa0kh%2FWQ%3D%3D" // 设备完整token

// OneNET MQTT服务器地址
#define MQTT_BROKERADDRESS "mqtts.heclouds.com"  // OneNET MQTT服务器地址，使用标准域名
#define MQTT_PORT          1883                   // MQTT服务器端口

// 定义主题 - 确保符合OneNET平台的主题规范
#define MQTT_PUBLISH_TOPIC     "$sys/aCwL6bRLK9/demo/thing/property/post"       // 发布主题
#define MQTT_SUBSCRIBE_TOPIC   "$sys/aCwL6bRLK9/demo/thing/property/post/reply" // 订阅主题-属性上报响应
#define MQTT_PROPERTY_SET_TOPIC "$sys/aCwL6bRLK9/demo/thing/property/set"       // 订阅主题-属性设置请求

// 创建WiFi和MQTT客户端
WiFiClient espClient;
PubSubClient client(espClient);

// 全局变量
typedef enum Key_Status
{
  Check,
  Down,
  Downing,
  Up
}KEY_STATUS;
// 按键相关变量
bool keyScanFlag = false;  // 按键扫描标志
KEY_STATUS KS = Check;
unsigned int Key_time = 10;
bool LED_Flag = false;

char Key_Value = 0;

unsigned long lastMsgTime = 0;
const int msgInterval = 2000;  // 消息发送间隔(毫秒)

int LED_status = 0;            // LED开关状态
int LED_actual_status = 0;     // LED实际状态（由光敏电阻控制）
int buzzer = 0;                // 蜂鸣器状态
bool Buzzer_Flag = false;      // 蜂鸣器标志位
float temperature = 0;
float humidity = 0;

DHT dht(DHT11_DAT, DHT11);


Ticker keyScanTimer;  // 创建定时器对象

// 按键扫描中断处理函数
void ICACHE_RAM_ATTR keyScanISR() {
  keyScanFlag = true;
}

void OLED_init()
{
  Wire.begin();
  oled.init();
  oled.clearDisplay();
}
void display_Data(float t,float h)
{
  oled.setTextXY(0,0);
  oled.putString("T: ");
  oled.setTextXY(0,11);
  oled.putFloat(t);
  oled.setTextXY(1,0);
  oled.putString("Humidity: ");
  oled.setTextXY(1,11);
  oled.putFloat(h);
}
// WiFi连接函数
void connectWiFi() {
  Serial.print("连接到WiFi: ");
  Serial.println(macUser_ESP8266_ApSsid);
  
  WiFi.begin(macUser_ESP8266_ApSsid, macUser_ESP8266_ApPwd);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println();
  Serial.println("WiFi连接成功");
  Serial.print("IP地址: ");
  Serial.println(WiFi.localIP());
}

// MQTT连接函数
void connectMQTT() {
  while (!client.connected()) {
    Serial.print("尝试连接MQTT服务器...");
    
    if (client.connect(MQTT_CLIENT_ID, MQTT_USER_NAME, MQTT_PASSWD)) {
      Serial.println("MQTT连接成功");
      
      // 订阅平台响应主题和属性设置主题
      if (client.subscribe(MQTT_SUBSCRIBE_TOPIC)) {
        Serial.println("订阅响应主题成功");
      } else {
        Serial.println("订阅响应主题失败");
      }
      
      if (client.subscribe(MQTT_PROPERTY_SET_TOPIC)) {
        Serial.println("订阅属性设置主题成功");
      } else {
        Serial.println("订阅属性设置主题失败");
      }
    } else {
      Serial.print("MQTT连接失败，状态码=");
      Serial.print(client.state());
      Serial.println(" 重试中...");
      delay(2000);
    }
  }
}

// MQTT消息回调函数
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("收到来自主题 [");
  Serial.print(topic);
  Serial.print("] 的消息: ");
  
  String message = "";
  for (unsigned int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  Serial.println(message);
  
  // 处理属性设置命令
  if (String(topic) == MQTT_PROPERTY_SET_TOPIC) {
    DynamicJsonDocument doc(1024);
    DeserializationError error = deserializeJson(doc, message);
    
    if (!error) {
      // 解析JSON命令
      if (doc.containsKey("params")) {
        JsonObject params = doc["params"];
        // 处理LED开关命令
        if (params.containsKey("LED_status")) {
          bool LED_s = params["LED_status"];
          Serial.print("收到LED开关命令: ");
          Serial.println(LED_s ? "开启" : "关闭");
          LED_status = LED_s ? 1 : 0;
        }
        if (params.containsKey("buzzer")) {
          bool buzzer_s = params["buzzer"];
          Serial.print("收到蜂鸣器开关命令: ");
          Serial.println(buzzer_s ? "开启" : "关闭");
          // 这里可以添加控制硬件的代码
          buzzer = buzzer_s ? 1 : 0;
        }
      }
      
      // 发送属性设置响应
      String response = "{\"id\":\"" + String(doc["id"].as<String>()) + "\",\"code\":200}";
      client.publish(MQTT_SUBSCRIBE_TOPIC, response.c_str());
      Serial.println("已发送属性设置响应: " + response);
    } else {
      Serial.println("JSON解析失败");
    }
  }
}

// 发送传感器数据到OneNET（不使用JSON库）
void sendSensorData(float temperature,int humidity, int LED_status,int LED_actual_status,int buzzer) {
  char payload[500];
  snprintf(payload, sizeof(payload), "{"
    "\"id\": \"123\","
    "\"version\": \"1.0\","
    "\"params\": {"
      "\"temperature\": {"
        "\"value\": %d"
      "},"
      "\"humidity\": {"
        "\"value\": %d"
      "},"
      "\"LED_status\": {"
        "\"value\": %d"
      "},"
      "\"LED_actual_status\": {"
        "\"value\": %d"
      "},"
      "\"buzzer\": {"
        "\"value\": %d"
      "}"
    "}"
  "}", (unsigned int)temperature, (unsigned int)humidity, LED_status, LED_actual_status, buzzer);
  
  // 发布消息到OneNET
  if (client.publish(MQTT_PUBLISH_TOPIC, payload)) {
    Serial.println("数据已发送: ");
    Serial.println(payload);
  } else {
    Serial.println("数据发送失败");
  }
}

// 优化的按键扫描函数
void ScanKey() {
  if (!keyScanFlag) return;  // 如果扫描标志未置位，直接返回
  switch(KS)
  {
    case Check:
      if(digitalRead(Key_1) == HIGH || digitalRead(Key_2) == HIGH)
      {
        KS = Down;
      }
    break;
    case Down:
      if(digitalRead(Key_1) == HIGH)   Key_Value = 1;
      if(digitalRead(Key_2) == HIGH)   Key_Value = 2;
      KS = Downing;
    break;
    case Downing:
      if(digitalRead(Key_1) == HIGH || digitalRead(Key_2) == HIGH)
      {
        Key_time += 10;
      }
      else
      {
        KS = Up;
      }
    break;
    case Up:
      Key_time = 10;
      KS = Check;
    break;
  }
  keyScanFlag = false;  // 清除扫描标志
}
void display_warning()
{
  static char count = 0;
  if(temperature >= 40 || humidity >= 80)
  {
    count = 1;
    if(temperature >= 40)
    {
      oled.setTextXY(2, 0);
      oled.putString("HIGH Temprature!");
    }
    if(humidity >= 80)
    {
      oled.setTextXY(3, 1);
      oled.putString("HIGH Humidity!");
    }
  }
  else
  {
    count = 0;
  }
  if(!count)
    oled.clearDisplay();
}
void display_sysconfig()
{
  oled.clearDisplay();
  oled.setTextXY(2, 0);
  oled.putString("in system config");
}
void display_init_over()
{
  oled.clearDisplay();
  oled.setTextXY(2, 1);
  oled.putString("SUCCESS!!");
}
void setup() {
  oled.clearDisplay();
  //实现OLED显示
  OLED_init();
  display_sysconfig();
  delay(500);
  //实现温湿度读取
  dht.begin();
  //实现LED控制
  pinMode(LED,OUTPUT);
  //初始化蜂鸣器IO口
  pinMode(Buzzer_IO, OUTPUT);
  digitalWrite(Buzzer_IO, HIGH);  // 确保蜂鸣器初始状态为关闭
  //初始化按键引脚
  pinMode(Key_1, INPUT);  // 修改为输入上拉模式
  pinMode(Key_2, INPUT_PULLUP);  // 修改为输入上拉模式
  pinMode(Key_Yin, OUTPUT); 
  digitalWrite(LED,HIGH);
  digitalWrite(Key_Yin,HIGH);
  
  //MQTT
  Serial.begin(115200);
  Serial.println("NodeMCU OneNET连接示例");
  
  // 初始化WiFi
  connectWiFi();
  
  // 设置MQTT服务器和回调函数
  client.setServer(MQTT_BROKERADDRESS, MQTT_PORT);
  client.setCallback(callback);
  
  // 连接MQTT
  connectMQTT();
  
  // 初始化定时器中断，每20ms触发一次
  keyScanTimer.attach_ms(10, keyScanISR);
  
  // 测试蜂鸣器
  digitalWrite(Buzzer_IO, LOW);
  delay(500);
  digitalWrite(Buzzer_IO, HIGH);
  display_init_over();
  delay(500);
  oled.clearDisplay();
}

void loop() {
  //实现OLED显示
  humidity = dht.readHumidity();//读湿度
  temperature = dht.readTemperature();//读温度(摄氏度)  
  display_Data(temperature,humidity);
  if(digitalRead(LDR_DO) == LOW)
    LED_actual_status = 1;
  else
    LED_actual_status = 0;
    
  //扫描按键
  ScanKey();
  
  // 处理按键1（蜂鸣器控制）
  if(Key_Value == 1 && Key_time == 10) {
    Key_Value = 0;  // 清除按键值
    Buzzer_Flag = !Buzzer_Flag;
    buzzer = Buzzer_Flag == 1 ? 1 : 0;
    Serial.print("蜂鸣器状态: "); Serial.println(buzzer);
  }
  // 处理按键2（LED控制）
  if(Key_Value == 2 && Key_time == 10) {
    Key_Value = 0;  // 清除按键值
    LED_Flag = !LED_Flag;
    LED_status = (LED_Flag == 1) ? 1 : 0;
    Serial.print("LED状态: "); Serial.println(LED_status);
    Serial.print("LED_Flag: ");Serial.println(LED_Flag);
  }
  
  // 控制LED
  if(LED_status) {
    digitalWrite(LED, LOW);
  } else {
    digitalWrite(LED, HIGH);
  }
  // 直接控制蜂鸣器
  if(buzzer) {
    digitalWrite(Buzzer_IO, LOW);  // 蜂鸣器开启
  } else {
    digitalWrite(Buzzer_IO, HIGH); // 蜂鸣器关闭
  }
  // 保持MQTT连接
  if (!client.connected()) {
    connectMQTT();
  }
  
  // 处理MQTT消息
  client.loop();
  
  // 定时发送传感器数据
  unsigned long now = millis();
  if (now - lastMsgTime > msgInterval) {
    lastMsgTime = now;
    sendSensorData(temperature,humidity,LED_status,LED_actual_status,buzzer);
  }
  
  // 添加调试信息
  static unsigned long lastDebugTime = 0;
  if (millis() - lastDebugTime > 1000) {  // 每秒打印一次
    Serial.print("Key1: "); Serial.print(digitalRead(Key_1));
    Serial.print("Key2: "); Serial.print(digitalRead(Key_2));
    Serial.print(" Key_Value: "); Serial.print(Key_Value);
    Serial.print(" Buzzer_Flag: "); Serial.print(Buzzer_Flag);
    Serial.print(" buzzer: "); Serial.println(buzzer);
    lastDebugTime = millis();
  }
}
